#include <iostream>
#include <memory>
#include <functional>
#include <unistd.h>
#include <cstdint>
#include <vector>
#include <unordered_map>

using task_cb = std::function<void()>;
using del_timer = std::function<void()>;
class TimerTask//对事件的定时功能进行封装，是对事件的封装
{
private:
    long unsigned int _id;//事件id
    unsigned int _timeout;//超时时间
    task_cb _cb;//删除任务的回调函数
    del_timer _delTimer;//删除任务结构体的回调函数，因为任务结构体保存在TimeWhell中，需要在其中定义函数
public:
    TimerTask(long unsigned int id, unsigned int timeout, task_cb cb)
    :_id(id),
    _timeout(timeout),
    _cb(cb)
    {}

    ~TimerTask()
    {
        _cb();
        _delTimer();
    }

    void set_delTimer(del_timer cb)
    {
        _delTimer = cb;
    }

    unsigned int get_timeout()
    {
        return _timeout;
    }
};

class TimeWheel//时间轮定时器，对封装后的事件进行组织
{
private:
    int _capicity;//时间轮大小,最大延迟时间
    int _tick;//时间指针所在的位置，每一个单位时间就移动一位。
    std::vector<std::vector<std::shared_ptr<TimerTask>>> _wheel;//时间轮
    std::unordered_map<long unsigned int, std::weak_ptr<TimerTask>> _timers;//用来查找有哪些事件进入时间轮，是对共享指针的观测，要用weak指针
public:
    TimeWheel(int capacity)
    :_capicity(capacity),
    _tick(0),
    _wheel(_capicity)
    {}

    void release_timer(long unsigned int id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(it);
        }
    }
    void add_timer(long unsigned int id, unsigned int timeout, const task_cb& cb)
    {
        std::shared_ptr<TimerTask> timer(new TimerTask(id, timeout, cb));//创建事件结构体
        timer->set_delTimer(std::bind(&TimeWheel::release_timer, this, id));//设置从时间轮删除事件的回调
        //将事件添加到时间轮
        unsigned int pos = (_tick + timeout) % _capicity;
        _wheel[pos].push_back(timer);
        //将事件添加到表中
        _timers[id] = (std::weak_ptr<TimerTask>) timer;
    }

    void flush_timer(long unsigned int id)
    {
        //在表中找timer
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            //没有这个事件，直接返回
            return;
        }
        else
        {
            auto timer = it->second.lock();//获取weak_ptr管理的对象对应的shared_ptr
            //将事件添加到时间轮
            unsigned int pos = (_tick + timer->get_timeout()) % _capicity;
            _wheel[pos].push_back(timer);
        }
    }

    void run_wheel()//时间轮转一次
    {
        unsigned int pos = _tick % _capicity;
        _wheel[pos].clear();
        _tick++;
    }
};

class test{
public:
    test()
    {
        std::cout << "构造" << std::endl;
    }
    ~test()
    {
        std::cout << "析构" << std::endl;
    }
};

void del_test(test* t)
{
    delete(t);
}

int main()
{
    TimeWheel time(5);
    test* t = new test();
    time.add_timer(0, 1, std::bind(del_test, t));

    for(int i = 0; i < 5; i++)
    { 
        std::cout << "flush" << std::endl;
        time.flush_timer(0);
        sleep(1);
    }
    while(1)
    {
        sleep(1);
        std::cout << "-----------------" << std::endl;
        time.run_wheel();
    }
    return 0;
}